from ipaddress import IPv4Network

from django import forms
from django.conf import settings
from django.core.exceptions import ValidationError
from django.shortcuts import render, redirect
from django.urls import re_path

from stark.service.v1 import StarkHandler, StarkModelForm, get_boolean_text, get_m2m_text
from web import models
from web.utils import ipv4_tools


class IpScopeModelForm(StarkModelForm):
    exclude_bootstrap_class = ['is_chart', ]

    class Meta:
        model = models.IpScope
        fields = ['ip_net', 'is_chart', 'service_type']

    def clean_ip_net(self):
        ip_net = self.cleaned_data['ip_net']
        try:
            IPv4Network(ip_net)
        except Exception as ex:
            raise ValidationError('你输入的网络地址不正确，请重新输入,网络地址示例:192.168.0.0/16')
        return ip_net


class IpScopeChangeModelForm(StarkModelForm):
    exclude_bootstrap_class = ['is_chart']

    class Meta:
        model = models.IpScope
        fields = ['ip_net', 'is_chart', 'service_type']
        widgets = {
            'ip_net': forms.TextInput(attrs={'class': 'form-control', 'readonly': True})
        }


class IpScopeHandler(StarkHandler):
    list_display = [StarkHandler.display_checkbox, 'ip_net', get_m2m_text('业务类型', 'service_type'),
                    get_boolean_text('是否显示图表', 'is_chart'), ]

    def get_model_class_form(self, is_add, request, pk, *args, **kwargs):
        if is_add:
            return IpScopeModelForm
        return IpScopeChangeModelForm

    def get_urls(self):
        """
        二次路由分发
        :return:
        """
        patterns = [
            re_path(r'^list/$', self.wrapper(self.list_view), name=self.get_list_url_name),
            re_path(r'^add/$', self.wrapper(self.add_view), name=self.get_add_url_name),
            re_path(r'^change/(?P<pk>\d+)/$', self.wrapper(self.change_view),
                    name=self.get_change_url_name),
            re_path(r'^delete/(?P<pk>\d+)/$', self.wrapper(self.delete_view),
                    name=self.get_delete_url_name)
        ]
        patterns.extend(self.extra_url())
        return patterns

    # def get_list_display(self, request, *args, **kwargs):
    #     """
    #     预留列表页面显示字段的钩子函数
    #     :return:
    #     """
    #     value = []
    #     if self.list_display:
    #         value.extend(self.list_display)
    #         permission_dict = request.session.get(settings.MOBILEDJ_PERMISSION_SESSION_KEY)
    #         if self.get_delete_url_name in permission_dict:
    #             value.append(type(self).display_delete)
    #     return value

    def action_multi_init(self, request, *args, **kwargs):
        """
        批量初始化子网
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        pk_list = request.POST.getlist('pk')
        for pk in pk_list:
            ip_network_object = IPv4Network(models.IpScope.objects.filter(id=pk).first().ip_net)
            if not ip_network_object:
                continue
            objects_exists = models.IpSubnet.objects.filter(ip_network_id=pk).exists()
            if objects_exists:
                continue
            prefix_length = ip_network_object.prefixlen

            # 自动初始化子网列表
            if prefix_length >= 24:
                ipv4_network_list = list(ip_network_object.subnets(new_prefix=prefix_length))
            else:
                ipv4_network_list = list(ip_network_object.subnets(new_prefix=24))
            ipv4_object_list = []
            for item in ipv4_network_list:
                ipv4_object_list.append(
                    models.IpSubnet(ip_network_id=pk, subnet=str(item.with_prefixlen),
                                    subnet_num=int(item.network_address)))
                print(item.network_address, int(item.network_address))
            models.IpSubnet.objects.bulk_create(ipv4_object_list, 100)

            # 自动初始化主机列表
            ipv4_subnet_list = models.IpSubnet.objects.filter(ip_network_id=pk)
            if not ipv4_subnet_list:
                continue
            ipv4_subnet_hosts_obj_list = []
            for item in ipv4_subnet_list:
                ipv4_subnet_host_exists = models.Hosts.objects.filter(ip_subnet_id=item.id).exists()
                if ipv4_subnet_host_exists:
                    continue
                ipv4_subnet = item.subnet
                ipv4_subnet_object = IPv4Network(ipv4_subnet)
                ipv4_hosts_list = [item for item in list(ipv4_subnet_object.hosts())]
                for host in ipv4_hosts_list:
                    temp_obj = models.Hosts(ip_address=str(host), ip_type_id=settings.UNUSE_IP_TYPE,
                                            ip_address_num=int(host),
                                            ip_subnet_id=item.id, )
                    ipv4_subnet_hosts_obj_list.append(temp_obj)
            models.Hosts.objects.bulk_create(ipv4_subnet_hosts_obj_list, batch_size=80)

    action_multi_init.text = '批量初始化子网'
    action_list = [action_multi_init, ]

    order_list = ['ip_net']

    def add_view(self, request, *args, **kwargs):
        """
        添加页面
        :return:
        """
        model_form_class = self.get_model_class_form(True, request, None, *args, **kwargs)
        if request.method == 'GET':
            form = model_form_class()
            return render(request, self.add_template or 'stark/change.html', {'form': form})
        form = model_form_class(data=request.POST)
        if form.is_valid():
            subnet = form.cleaned_data['ip_net']
            subnet_list = [item.ip_net for item in models.IpScope.objects.all()]
            flag = ipv4_tools.check_valid_subnet(subnet, child_subnet_list=subnet_list)
            if flag:
                response = self.save(request, form, False, *args, **kwargs)
                return response or redirect(self.reverse_list_url(*args, **kwargs))
            else:
                form.add_error('ip_net', '你输入的网段范围重叠，请重新输入')
        return render(request, self.add_template or 'stark/change.html', {'form': form})
